#ifndef BASECAMERAOBJECT_H_INCLUDED
#define BASECAMERAOBJECT_H_INCLUDED

// predecl

// includes
#include <Math/Vector.hpp>
#include <Math/Matrix4x4.hpp>
#include <Math/Rect.hpp>

#include "EmptyObject.h"
//#include <RenderSubSystem/Renderinglayer.h>
namespace cvObjects
{
	/**
	 *	CameraObject.
	 *	class is completed in RenderingSubSystem.
	 */
	class BaseCameraObject : public EmptyObject
	{
		public:
			/** ### ObjectSubSystem perspective ### */

			/** Construct a EmptyObject */
			// static EmptyObject * create(); <we can't allocate abstract object.>
			/// Creates a duplicate of the object.
			virtual BaseCameraObject * copy( cvMath::bitfield_t flags ) = 0;

			virtual void destroy() = 0;

			/** Type of the object */
			virtual int objectType() const;

			/** Object parenting */
			virtual void setRelativity( cvMath::bitfield_t flags );

			/// Setters
			void viewport( int x, int y, int w, int h );
			void zoom( float factor, float x = 1.0f, float y = 1.0f );
			void zoomin( float factor, float x = 0.0f, float y = 0.0f );
			void zoomout( float factor, float x = 0.0f, float y = 0.0f );
			void offset( const cvMath::Vec2f & p );

			/// Getters
			const cvMath::Recti & viewport();
			const cvMath::Vec2f & zoom();
			const cvMath::Vec2f & offset();

			///	Camera coordinate mode.
			virtual void useWorldCoordinates() = 0;
			virtual void useScreenCoordinates() = 0;

			/** ### RenderSubSystem perspective ### */

			// Setups camera
			virtual void setup() = 0;

			// Calculates Camera bounding box in current coordinate mode space.
			// pre-condition: setup() must be called first to update internal state.
			virtual cvMath::Rectf getBoundingBox() =0;

		protected:
			BaseCameraObject();

			virtual void updater();

			cvMath::Vec2f	m_offset;
			cvMath::Vec2f	m_zoom, m_localzoom;
			cvMath::Recti	m_viewport, m_localviewport;

		private:

			typedef void ( BaseCameraObject::*relativity_fn )();
			void viewport_zoom_update();
			void viewport_update();
			void zoom_update();
			relativity_fn fn_updater;

			// spawn of viewport() setter
			typedef void ( BaseCameraObject::*viewport_fn )( int, int, int, int );
			void viewport_glb( int, int, int, int );
			void viewport_local( int, int, int, int );
			viewport_fn fn_viewport;

			// spawn of zoom() setter
			typedef void ( BaseCameraObject::*zoom_fn )( const cvMath::Vec2f& );
			void zoom_glb( const cvMath::Vec2f& );
			void zoom_local( const cvMath::Vec2f& );
			void zoom_localx( const cvMath::Vec2f& );
			void zoom_localy( const cvMath::Vec2f& );
			zoom_fn fn_zoom;
	};
};
#endif // BASECAMERAOBJECT_H_INCLUDED
